<template>
  <div class="game-container">
    <canvas ref="gameCanvas" :width="canvasWidth" :height="canvasHeight"></canvas>
  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';

// 使用 ref 来获取对 canvas 的引用
const gameCanvas = ref(null);

const canvasWidth = ref(window.innerWidth > 480 ? 480 : window.innerWidth);
const canvasHeight = ref(window.innerHeight > 650 ? 650 : window.innerHeight - 20);
let ctx = null;

const PHASE_DOWNLOAD = 1;
const PHASE_READY = 2;
const PHASE_LOADING = 3;
const PHASE_PLAY = 4;
const PHASE_PAUSE = 5;
const PHASE_GAMEOVER = 6;

let curPhase = PHASE_DOWNLOAD;
let gameScore = 0;

let gameLoop = null;

  
  // 图片资源的相对路径，直接用 import 静态导入，或者用 require（如使用 Webpack）
  const imgName = [
    new URL("../plane/background.png", import.meta.url).href,
    new URL('../plane/game_pause_nor.png', import.meta.url).href,
    new URL('../plane/m1.png', import.meta.url).href,
    new URL('../plane/start.png', import.meta.url).href,
    [
      new URL('../plane/enemy1.png', import.meta.url).href,
      new URL('../plane/enemy1_down1.png', import.meta.url).href,
      new URL('../plane/enemy1_down2.png', import.meta.url).href,
      new URL('../plane/enemy1_down3.png', import.meta.url).href,
      new URL('../plane/enemy1_down4.png', import.meta.url).href,
    ],
    [
      new URL('../plane/enemy2.png', import.meta.url).href,
      new URL('../plane/enemy2_down1.png', import.meta.url).href,
      new URL('../plane/enemy2_down2.png', import.meta.url).href,
      new URL('../plane/enemy2_down3.png', import.meta.url).href,
      new URL('../plane/enemy2_down4.png', import.meta.url).href,
    ],
    [
      new URL('../plane/enemy3_n1.png', import.meta.url).href,
      new URL('../plane/enemy3_n2.png', import.meta.url).href,
      new URL('../plane/enemy3_hit.png', import.meta.url).href,
      new URL('../plane/enemy3_down1.png', import.meta.url).href,
      new URL('../plane/enemy3_down2.png', import.meta.url).href,
      new URL('../plane/enemy3_down3.png', import.meta.url).href,
      new URL('../plane/enemy3_down4.png', import.meta.url).href,
      new URL('../plane/enemy3_down5.png', import.meta.url).href,
      new URL('../plane/enemy3_down6.png', import.meta.url).href,
    ],
    [
      new URL('../plane/game_loading1.png', import.meta.url).href,
      new URL('../plane/game_loading2.png', import.meta.url).href,
      new URL('../plane/game_loading3.png', import.meta.url).href,
      new URL('../plane/game_loading4.png', import.meta.url).href,
    ],
    [
      new URL('../plane/hero1.png', import.meta.url).href,
      new URL('../plane/hero2.png', import.meta.url).href,
      new URL('../plane/hero_blowup_n1.png', import.meta.url).href,
      new URL('../plane/hero_blowup_n2.png', import.meta.url).href,
      new URL('../plane/hero_blowup_n3.png', import.meta.url).href,
      new URL('../plane/hero_blowup_n4.png', import.meta.url).href,
    ],
  ];
  
  let bg = null,
  pause = null,
  m = null,
  startImg = null,
  enemy1 = [],
  enemy2 = [],
  enemy3 = [],
  gameLoad = [],
  heroImg = [];
let progress = 1;
  
  function download() {
    bg = nImg(imgName[0]);
    pause = nImg(imgName[1]);
    m = nImg(imgName[2]);
    startImg = nImg(imgName[3]);
    for (let i = 0; i < imgName[4].length; i++) {
      enemy1[i] = nImg(imgName[4][i]);
    }
    for (let i = 0; i < imgName[5].length; i++) {
      enemy2[i] = nImg(imgName[5][i]);
    }
    for (let i = 0; i < imgName[6].length; i++) {
      enemy3[i] = nImg(imgName[6][i]);
    }
    for (let i = 0; i < imgName[7].length; i++) {
      gameLoad[i] = nImg(imgName[7][i]);
    }
    for (let i = 0; i < imgName[8].length; i++) {
      heroImg[i] = nImg(imgName[8][i]);
    }
  
    function nImg(src) {
      const img = new Image();
      img.src = src;
      img.onload = imgLoad;
      return img;
    }
  
    function imgLoad() {
        progress += 3;
        ctx.clearRect(0, 0, canvasWidth.value, canvasHeight.value);
        const text = `${progress}%`;
        const tw = ctx.measureText(text).width;
        ctx.font = '60px arial';
        ctx.fillStyle = 'red';
        ctx.fillText(text, (canvasWidth.value - tw) / 2, canvasHeight.value / 2);
        console.log('Image loaded, progress:', progress);
        if (progress >= 100) {
            console.log('All images loaded, starting game.');
            start();
        }
    }
  }
  
  function start() {
    curPhase = PHASE_READY;
    ctx.canvas.onclick = function () {
      curPhase == PHASE_READY && (curPhase = PHASE_LOADING);
    };
    ctx.fillStyle = '#963';
    ctx.font = '24px arial';
    hero = new Hero();
    gameEngine();
  }
  
  function paintBg() {
    let y = 0;
    return function () {
      console.log('Drawing background');
      ctx.drawImage(bg, 0, y);
      ctx.drawImage(bg, 0, y - 852);
      y++ == 852 && (y = 0);
    };
  }
  
  function paintLogo() {
    ctx.drawImage(startImg, 40, 0);
  }
  
  function loading() {
    let index = 0;
    return function () {
      if (index % 1 == 0) ctx.drawImage(gameLoad[index], 0, canvasHeight.value - gameLoad[0].height);
      index += 0.5;
      if (index > 3) {
        curPhase = PHASE_PLAY;
        index = 0;
      }
    };
  }
  
  let hero = null;
  
  function Hero() {
    this.x = (canvasWidth.value - heroImg[0].width) / 2;
    this.y = canvasHeight.value - heroImg[0].height;
    this.index = 0;
    this.count = 0;
    this.hCount = 0;
    this.eCount = 0;
    this.n = 0;
    this.life = 0;
    this.draw = function () {
      this.count++;
      this.hit();
      if (this.index > 4) {
        curPhase = PHASE_GAMEOVER;
        this.index = 5;
      }
      if (this.count % 3 == 0 && this.index <= 1) {
        this.index = this.index == 0 ? 1 : 0;
        this.count = 0;
      }
      ctx.drawImage(heroImg[this.index], this.x, this.y);
      ctx.fillText('SCORE:' + gameScore, 10, 30);
      this.hCount++;
      if (this.hCount % 3 == 0) {
        this.n == 32 && (this.n = 0);
        hullet.push(new Hullet(this.n));
        this.n == 0 && (this.n = -32);
        hullet.push(new Hullet(this.n));
        this.n == -32 && (this.n = 32);
        hullet.push(new Hullet(this.n));
        this.hCount = 0;
      }
      this.eCount++;
      if (this.eCount % 8 == 0) {
        liveEnemy.push(new Enemy());
        this.eCount = 0;
      }
    };
  
    this.hit = function () {
      for (let i = 0; i < liveEnemy.length; i++) {
        const d = liveEnemy[i];
        const px = this.x <= d.x ? d.x : this.x;
        const py = this.y <= d.y ? d.y : this.y;
  
        if (
          px >= this.x &&
          px <= this.x + heroImg[0].width &&
          py >= this.y &&
          py <= this.y + heroImg[0].height &&
          px >= d.x &&
          px <= d.x + d.width &&
          py >= d.y &&
          py <= d.y + d.height
        ) {
          this.life++;
          if (this.life > 30) {
            if (this.index <= 2) {
              this.index = 3;
            }
            this.index++;
            this.life = 0;
          }
        }
      }
    };
  
    function move(e) {
      if (curPhase == PHASE_PLAY || curPhase == PHASE_PAUSE) {
        curPhase = PHASE_PLAY;
        const offsetX = e.offsetX || e.touches[0].pageX;
        const offsetY = e.offsetY || e.touches[0].pageY;
        const w = heroImg[0].width,
          h = heroImg[0].height;
        let nx = offsetX - w / 2,
          ny = offsetY - h / 2;
        nx < 20 - w / 2
          ? (nx = 20 - w / 2)
          : nx > ctx.canvas.width - w / 2 - 20
          ? (nx = ctx.canvas.width - w / 2 - 20)
          : 0;
        ny < 0 ? (ny = 0) : ny > ctx.canvas.height - h / 2 ? (ny = ctx.canvas.height - h / 2) : 0;
        hero.x = nx;
        hero.y = ny;
        hero.count = 2;
      }
    }
  
    ctx.canvas.addEventListener('mousemove', move, false);
    ctx.canvas.addEventListener('touchmove', move, false);
    ctx.canvas.onmouseout = function (e) {
      if (curPhase == PHASE_PLAY) {
        curPhase = PHASE_PAUSE;
      }
    };
  }
  
  const hullet = [];
  
  function Hullet(n) {
    this.n = n;
    this.mx = hero.x + (heroImg[0].width - m.width) / 2 + this.n;
    this.my = this.n == 0 ? hero.y - m.height : hero.y + m.height;
    this.width = m.width;
    this.height = m.height;
    this.removable = false;
  }
  
  Hullet.drawHullet = function () {
    for (let i = 0; i < hullet.length; i++) {
      hullet[i].draw();
      if (hullet[i].removable) {
        hullet.splice(i, 1);
      }
    }
  };
  
  Hullet.prototype.draw = function () {
    ctx.drawImage(m, this.mx, this.my);
    this.my -= 20;
    this.mx += this.n == 32 ? 3 : this.n == -32 ? -3 : 0;
    if (this.my < -m.height) {
      this.removable = true;
    }
  };
  
  const liveEnemy = [];
  
  function Enemy() {
    this.n = Math.random() * 20;
    this.enemy = null;
    this.speed = 0;
    this.lifes = 2;
    if (this.n < 1) {
      this.enemy = enemy3[0];
      this.speed = 2;
      this.lifes = 50;
    } else if (this.n < 6) {
      this.enemy = enemy2[0];
      this.speed = 4;
      this.lifes = 10;
    } else {
      this.enemy = enemy1[0];
      this.speed = 6;
    }
    this.x = parseInt(Math.random() * (ctx.canvas.width - this.enemy.width));
    this.y = -this.enemy.height;
    this.width = this.enemy.width;
    this.height = this.enemy.height;
    this.index = 0;
    this.removable = false;
    this.die = false;
    this.draw = function () {
      if (this.speed == 2) {
        if (this.die) {
          if (this.index < 2) {
            this.index = 3;
          }
          if (this.index < enemy3.length) {
            this.enemy = enemy3[this.index++];
          } else {
            this.removable = true;
          }
        } else {
          this.enemy = enemy3[this.index];
          this.index == 0 ? (this.index = 1) : (this.index = 0);
        }
      } else if (this.die) {
        if (this.index < enemy1.length) {
          if (this.speed == 6) {
            this.enemy = enemy1[this.index++];
          } else {
            this.enemy = enemy2[this.index++];
          }
        } else {
          this.removable = true;
        }
      }
      ctx.drawImage(this.enemy, this.x, this.y);
      this.y += this.speed;
      this.hit();
      if (this.y > ctx.canvas.height) {
        this.removable = true;
      }
    };
    this.hit = function () {
      for (let i = 0; i < hullet.length; i++) {
        const h = hullet[i];
        if (
          this.x + this.width >= h.mx &&
          h.mx + h.width >= this.x &&
          h.my + h.height >= this.y &&
          this.height + this.y >= h.my
        ) {
          if (--this.lifes == 0) {
            this.die = true;
            gameScore += this.speed == 6 ? 10 : this.speed == 4 ? 20 : 100;
          }
          h.removable = true;
        }
      }
    };
  }
  
  function drawEnemy() {
    for (let i = 0; i < liveEnemy.length; i++) {
      if (liveEnemy[i].removable) {
        liveEnemy.splice(i, 1);
      }
    }
    for (let i = 0; i < liveEnemy.length; i++) {
      liveEnemy[i].draw();
    }
  }
  
  function drawPause() {
    ctx.drawImage(pause, (canvasWidth.value - pause.width) / 2, (canvasHeight.value - pause.height) / 2);
  }
  
  function gameover() {
    alert(`游戏结束，成绩: ${gameScore}`);
    gameScore = 0;
    curPhase = PHASE_READY;
    hero = null;
    hero = new Hero();
  }
  
  let pBg = paintBg();
  let load = loading();
  
  
function gameEngine() {
  console.log('Game Engine Running');
  switch (curPhase) {
    case PHASE_READY:
      pBg();
      paintLogo();
      break;
    case PHASE_LOADING:
      pBg();
      load();
      break;
    case PHASE_PLAY:
      pBg();
      drawEnemy();
      Hullet.drawHullet();
      hero.draw();
      break;
    case PHASE_PAUSE:
      drawPause();
      break;
    case PHASE_GAMEOVER:
      gameover();
      break;
  }
}

function startGameLoop() {
  gameLoop = setInterval(gameEngine, 50);
}

function stopGameLoop() {
  clearInterval(gameLoop);
  gameLoop = null;
}

function handleVisibilityChange() {
  if (document.visibilityState === 'hidden') {
    stopGameLoop();
    console.log('Game paused');
  } else if (document.visibilityState === 'visible') {
    startGameLoop();
    console.log('Game resumed');
  }
}

onMounted(() => {
  console.log('Mounted PlaneGame.vue');
  const canvas = gameCanvas.value; // 获取 canvas 的引用
  if (canvas) {
    ctx = canvas.getContext('2d');
    console.log('Canvas Context Initialized:', ctx);
    download();
    startGameLoop();
  } else {
    console.error('Canvas not found');
  }

  document.addEventListener('visibilitychange', handleVisibilityChange);
});

onBeforeUnmount(() => {
  document.removeEventListener('visibilitychange', handleVisibilityChange);
  stopGameLoop();
});
</script>

<style scoped>
.game-container {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
}

canvas {
  border: 1px solid black;
}
</style>
  